package com.example.rwq_test.aqs;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

/**
 * TODO: CyclicBarrier并不是继承AQS的,写在这里是因为他们有对比性
 * 模拟三个场景: 公司组织游玩
 *  场景一(run1方法): 中午吃饭,大家到齐了才能吃饭,  如果barrier改成5,那就五个人一桌,那桌先到齐,那桌先吃
 *  场景二(run2方法): 在场景一的基础上再添加吃完饭后所有人去车上,都到齐后再出发去景点;
 *  场景三(run方法): 在场景一的基础上再添加,最后一个到的要给大家倒酒赔不是后再开饭
 *
 *
 * @author renweiqiang
 * @version 1.0.0
 * @createTime 2024/3/28
 */
@Slf4j
public class CyclicBarrierDemo {
    public static CyclicBarrier cyclicBarrier = new CyclicBarrier(10);

    public static CyclicBarrier cyclicBarrier1 = new CyclicBarrier(10, () -> {
        //模拟倒酒，花了2秒，又得让其他9个人等2秒
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "说，不好意思，让大家久等了，给大家倒酒赔罪!");
    });

    public static class T extends Thread {
        int sleep;

        public T(String name, int sleep) {
            super(name);
            this.sleep = sleep;
        }

//        /**
//         * 10个人到齐了,才能吃饭
//         */
//        @Override
//        public void run1() {
//            try {
//                //模拟休眠
//                TimeUnit.SECONDS.sleep(sleep);
//                long starTime = System.currentTimeMillis();
//                //调用await()的时候，当前线程将会被阻塞，需要等待其他员工都到达await了才能继续
//                cyclicBarrier.await();
//                long endTime = System.currentTimeMillis();
//                System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),开始吃饭了！");
//            } catch (Exception e) {
//                log.error("Worker run Exception.", e);
//            }
//        }

        //等待吃饭
        void eat() {
            try {
                //模拟休眠
                TimeUnit.SECONDS.sleep(sleep);
                long starTime = System.currentTimeMillis();
                //调用await()的时候，当前线程将会被阻塞，需要等待其他员工都到达await了才能继续
                cyclicBarrier.await();
                long endTime = System.currentTimeMillis();
                System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),开始吃饭了！");

                //休眠sleep时间，模拟当前员工吃饭耗时
                TimeUnit.SECONDS.sleep(sleep);
            } catch (Exception e) {
                log.error("Worker run Exception.", e);
            }
        }

        //等待所有人到齐之后，开车去下一站
        void drive() {
            try {
                long starTime = System.currentTimeMillis();
                //调用await()的时候，当前线程将会被阻塞，需要等待其他员工都到达await了才能继续
                cyclicBarrier.await();
                long endTime = System.currentTimeMillis();
                System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),去下一景点的路上！");
            } catch (Exception e) {
                log.error("Worker run Exception.", e);
            }
        }


        /**
         * 等待所有人到齐之后吃饭，先到的人坐那等着，什么事情不要干
         * 等待所有人到齐之后开车去下一景点，先到的人坐那等着，什么事情不要干
         */
        @Override
        public void run() {
            //等待所有人到齐之后吃饭，先到的人坐那等着，什么事情不要干
            this.eat();
            //等待所有人到齐之后开车去下一景点，先到的人坐那等着，什么事情不要干
            this.drive();
        }

//        @Override
//        public void run() {
//            try {
//                //模拟休眠
//                TimeUnit.SECONDS.sleep(sleep);
//                long starTime = System.currentTimeMillis();
//                //调用await()的时候，当前线程将会被阻塞，需要等待其他员工都到达await了才能继续
//                cyclicBarrier1.await();
//                long endTime = System.currentTimeMillis();
//                System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),开始吃饭了！");
//            } catch (Exception e) {
//                log.error("Worker run Exception.", e);
//            }
//        }
    }

    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            new T("员工" + i, i).start();
        }
    }
}
